package com.bytz.modules.cms.user.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.bytz.common.constant.BooleanConstant;
import com.bytz.common.constant.CommonConstant;
import com.bytz.common.exception.BytzBootException;
import com.bytz.modules.cms.productLine.entity.ProductLine;
import com.bytz.modules.cms.productLine.service.IProductLineService;
import com.bytz.modules.cms.user.constants.CmsSysUserConstants;
import com.bytz.modules.cms.user.entity.CmsSysUser;
import com.bytz.modules.cms.user.mapper.CmsSysUserMapper;
import com.bytz.modules.cms.user.service.ICmsSysUserService;
import com.bytz.modules.system.entity.*;
import com.bytz.modules.system.service.ISysUserService;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class CmsSysUserServiceImpl extends MPJBaseServiceImpl<CmsSysUserMapper, CmsSysUser> implements ICmsSysUserService {

    @Autowired
    private IProductLineService productLineService;

    @Autowired
    private ISysUserService sysUserService;

    @Override
    public List<CmsSysUser> getByIds(Collection<String> ids) {

        if (CollectionUtil.isEmpty(ids)) {
            return new ArrayList<>();
        }

        return lambdaQuery().in(SysUser::getId, ids).list();
    }

    @Transactional(rollbackFor = Exception.class)
    public CmsSysUser addUser(CmsSysUser sysUser, String selectedRoles, String selectedDeparts) {
        SysUser user = sysUserService.addUser(sysUser, selectedRoles, selectedDeparts);
        lambdaUpdate().eq(SysUser::getId, user.getId())
                .set(CmsSysUser::getShortName, sysUser.getShortName())
                .set(CmsSysUser::getArea, sysUser.getArea())
                .set(CmsSysUser::getBusinessPartnerId, sysUser.getBusinessPartnerId())
                .set(CmsSysUser::getOrderManagerId, sysUser.getOrderManagerId())
                .update();
        return sysUser;
    }

    @Transactional(rollbackFor = Exception.class)
    public CmsSysUser editUser(CmsSysUser sysUser, String selectedRoles, String selectedDeparts) {
        SysUser user = sysUserService.editUser(sysUser, selectedRoles, selectedDeparts);
        lambdaUpdate().eq(SysUser::getId, user.getId())
                .set(CmsSysUser::getShortName, sysUser.getShortName())
                .set(CmsSysUser::getArea, sysUser.getArea())
                .set(CmsSysUser::getBusinessPartnerId, sysUser.getBusinessPartnerId())
                .set(CmsSysUser::getOrderManagerId, sysUser.getOrderManagerId())
                .update();
        return sysUser;
    }

    @Override
    public List<CmsSysUser> getUserByRoleAndDept(String roleName, String roleCode, String roleId, String deptId, String deptName) {

        boolean hasRole = StringUtils.isNotBlank(roleCode) || StringUtils.isNotBlank(roleId) || StringUtils.isNotBlank(roleName);
        boolean hasDepart = StringUtils.isNotBlank(deptName) || StringUtils.isNotBlank(deptId);
        MPJLambdaWrapper<CmsSysUser> objectMPJLambdaWrapper = new MPJLambdaWrapper<CmsSysUser>()
                .selectAll(CmsSysUser.class)
                .leftJoin(hasRole, SysUserRole.class, SysUserRole::getUserId, CmsSysUser::getId)
                .leftJoin(hasRole, SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .leftJoin(hasDepart, SysUserDepart.class, SysUserDepart::getUserId, SysUser::getId)
                .leftJoin(hasDepart, SysDepart.class, on ->
                        on.eq(SysDepart::getId, SysUserDepart::getDepId)
                                .eq(SysDepart::getDelFlag, BooleanConstant.INT_FALSE)
                )
                .eq(StringUtils.isNotBlank(deptId), SysDepart::getId, deptId)
                .eq(StringUtils.isNotBlank(roleName), SysRole::getRoleName, roleName)
                .eq(StringUtils.isNotBlank(roleCode), SysRole::getRoleCode, roleCode)
                .eq(StringUtils.isNotBlank(roleId), SysRole::getId, roleId)
                .eq(StringUtils.isNotBlank(deptName), SysDepart::getDepartName, deptName);

        return super.selectJoinList(CmsSysUser.class, objectMPJLambdaWrapper);
    }

    @Override
    public List<CmsSysUser> getUsersByRoleCode(String roleCode) {

        MPJLambdaWrapper<CmsSysUser> wrapper = new MPJLambdaWrapper<CmsSysUser>()
                .selectAll(CmsSysUser.class)
                .leftJoin(SysUserRole.class, SysUserRole::getUserId, CmsSysUser::getId)
                .leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .eq(SysRole::getRoleCode, roleCode);

        return baseMapper.selectJoinList(CmsSysUser.class, wrapper);
    }

    @Override
    public List<CmsSysUser> getSales(String productLineId) {

        if (StringUtils.isBlank(productLineId)) {
            productLineId = productLineService.getLoginUserLine().map(ProductLine::getId).orElse(null);
        }

        MPJLambdaWrapper<CmsSysUser> wrapper = new MPJLambdaWrapper<>();

        return baseMapper.selectJoinList(CmsSysUser.class, wrapper
                .selectAll(CmsSysUser.class)
                .innerJoin(SysUserRole.class, SysUserRole::getUserId, CmsSysUser::getId)
                .innerJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .innerJoin(ProductLine.class, ProductLine::getDeptId, CmsSysUser::getCurrentDeptId)
                .eq(ProductLine::getDelFlag, CommonConstant.DEL_FLAG_0)
                .eq(StringUtils.isNotBlank(productLineId), ProductLine::getId, productLineId)
                .in(SysRole::getRoleCode, Sets.newHashSet(CmsSysUserConstants.RoleCode.REGION_SALES_MANAGER, CmsSysUserConstants.RoleCode.SALES)));
    }

    @Override
    public String getOMEmailBySaleIds(String saleId) {
        CmsSysUser sale = lambdaQuery()
                .select(CmsSysUser::getOrderManagerId)
                .eq(SysUser::getId, saleId)
                .one();
        return lambdaQuery()
                .select(SysUser::getEmail)
                .eq(SysUser::getId, sale.getOrderManagerId())
                .oneOpt()
                .orElseThrow(() -> new BytzBootException(String.format("销售%s没有设置对应的om", sale.getRealname())))
                .getEmail();
    }

    @Override
    public CmsSysUser getOMBySaleIds(String saleId) {
        CmsSysUser sale = lambdaQuery()
                .select(CmsSysUser::getOrderManagerId)
                .eq(SysUser::getId, saleId)
                .oneOpt().orElseThrow(() -> new BytzBootException("销售没有设置对应的om"));
        return lambdaQuery()
                .eq(SysUser::getId, sale.getOrderManagerId())
                .oneOpt()
                .orElseThrow(() -> new BytzBootException(String.format("销售%s没有设置对应的om", sale.getRealname())));
    }

    @Override
    public List<String> getSalesIdsByRegionManager(String id) {
        CmsSysUser user = getById(id);
        MPJLambdaWrapper<CmsSysUser> wrapper = new MPJLambdaWrapper<>();
        return baseMapper.selectJoinList(String.class, wrapper
                .select(CmsSysUser::getId)
                .innerJoin(SysUserRole.class, SysUserRole::getUserId, CmsSysUser::getId)
                .innerJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
                .eq(SysRole::getRoleCode, CmsSysUserConstants.RoleCode.SALES)
                .eq(CmsSysUser::getArea, user.getArea())
                .eq(CmsSysUser::getCurrentDeptId, user.getCurrentDeptId()));
    }

    @Override
    public List<CmsSysUser> getByRealNames(Collection<String> names) {
        return lambdaQuery().in(SysUser::getRealname, names).list();
    }

    @Override
    public Set<String> getSalesIdsByOM(String orderManagerId) {
        return lambdaQuery()
                .eq(CmsSysUser::getOrderManagerId, orderManagerId)
                .select(CmsSysUser::getId)
                .list().stream()
                .map(CmsSysUser::getId)
                .collect(Collectors.toSet());
    }
}